﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;

using Chronicle.Analyzation;
using Chronicle.Parser;

namespace Chronicle.Modules
{
	class DeathModule : AnalyzeModule
	{
		public override string Name {
			get {
				return "Deaths";
			}
		}

		private AnalyzeVisitor visitor;
		public override void Attach (AnalyzeVisitor visitor)
		{
			this.visitor = visitor;
			visitor.EventHeal  += HandleEvent;
			visitor.EventDamage += HandleEvent;

			visitor.EventDie += HandleDeathEvent;
			visitor.EventTargetKilled += HandleDeathEvent;
		}

		class Death
		{
			public DateTime TimeStamp;
			public string Attacker;
			public LinkedList<Event> combatLog = new LinkedList<Event> ();
		}

		class DeathTag
		{
			public List<Death> Deaths = new List<Death>();
		}

		void HandleDeathEvent (object sender, EventEventArgs e)
		{
			var curEvent = visitor.curEvent;
			var eventDamage = e.Event;
			var actor = curEvent.GetTarget(eventDamage);
			var tagData = actor.GetTagData (() => new DeathTag());
			var newDeath = new Death();
			newDeath.TimeStamp = e.Event.TimeStamp;
			foreach (var eventBefore in messageList.Where (msg => msg.TargetId == e.Event.TargetId)) {
				newDeath.combatLog.AddFirst (eventBefore);
			}
			newDeath.combatLog.AddFirst (e.Event);
			newDeath.Attacker = e.Event.ActorName;
			tagData.Deaths.Add(newDeath);
			
			actor = visitor.allEvents.GetTarget(eventDamage);
			tagData = actor.GetTagData (() => new DeathTag());
			tagData.Deaths.Add(newDeath);
		}

		public override int Compare (Actor left, Actor right)
		{
			return left.GetTagData (() => new DeathTag()).Deaths.Count.CompareTo (right.GetTagData (() => new DeathTag()).Deaths.Count);
		}
		
		public override string GetHintText(EventInformation eventInformation, Actor actor)
		{
			var tagData = actor.GetTagData (() => new DeathTag());
			return "(" + tagData.Deaths.Count + " deaths)";
		}

		private LinkedList<Event> messageList = new LinkedList<Event>();
		private void HandleEvent(object sender, EventEventArgs e)
		{
			if (messageList.Count > 200)
				messageList.RemoveFirst();
			messageList.AddLast(new LinkedListNode<Event>(e.Event));
		}
		
		class DeathContainer {
			public Death Death { get; set; }
			public string Text { get; set; }
		}
		class DetailsContainer {
			public string Time { get; set; }
			public string Message { get; set; }
		}
		public override void CreateDetailsView(ListView abilities, ListView details, Actor actor)
		{
			var abilityGrid = new GridView ();
			abilities.View = abilityGrid;
			abilityGrid.Columns.Add (new GridViewColumn () { HeaderContainerStyle = null, DisplayMemberBinding = new Binding("Text")});
		
			var tagData = actor.GetTagData (() => new DeathTag());
			abilities.ItemsSource = tagData.Deaths.Select (d => new DeathContainer () {
			                                               	Death = d,
			                                               	Text = d.TimeStamp.ToShortTimeString() + " by " + d.Attacker
			});

			var detailsGrid = new GridView ();
			details.View = detailsGrid;
			detailsGrid.Columns.Add (new GridViewColumn () { Header = "Time", DisplayMemberBinding = new Binding("Time")});
			detailsGrid.Columns.Add (new GridViewColumn () { Header = "Message", DisplayMemberBinding = new Binding("Message")});
			
			abilities.SelectionChanged += delegate(object sender, SelectionChangedEventArgs e) { 
				var d = (DeathContainer)e.AddedItems[0];
				if (d == null)
					return;
				
				details.ItemsSource = d.Death.combatLog.Select (evt => new DetailsContainer () {
				                                                	Time = (evt.TimeStamp - d.Death.TimeStamp).ToString (),
				                                               		Message = evt.Message
				});
				
			};
		}
	}
}
